Перейти к основному содержимому

5.02. Справочник по Flask

Разработчику Архитектору

Справочник по Flask

1. Основные компоненты приложения

Flask

Основной класс приложения во Flask. Создание экземпляра этого класса инициализирует веб-приложение.

from flask import Flask
app = Flask(__name__)

Параметры конструктора:

  • import_name — имя модуля или пакета приложения. Обычно передаётся __name__.
  • static_url_path — URL-префикс для статических файлов. По умолчанию /static.
  • static_folder — путь к папке со статическими файлами. По умолчанию 'static'.
  • static_host — хост для обслуживания статики (требуется при использовании поддоменов).
  • host_matching — включает сопоставление хостов для всех правил маршрутизации.
  • subdomain_matching — включает сопоставление поддоменов.
  • template_folder — путь к папке с шаблонами. По умолчанию 'templates'.
  • instance_path — абсолютный путь к папке экземпляра приложения.
  • instance_relative_config — загружать ли конфигурацию относительно папки экземпляра.
  • root_path — корневой путь приложения. По умолчанию определяется автоматически.

Свойства экземпляра Flask

  • name — имя приложения, совпадает с import_name.
  • config — объект конфигурации (Config), содержит все настройки приложения.
  • jinja_env — экземпляр среды Jinja2, используемый для рендеринга шаблонов.
  • url_map — карта URL-адресов (Map из Werkzeug), содержит все зарегистрированные маршруты.
  • before_request_funcs, after_request_funcs, teardown_request_funcs — списки обработчиков соответствующих событий.
  • blueprints — словарь зарегистрированных Blueprint’ов.
  • extensions — словарь расширений, привязанных к приложению.

2. Конфигурация приложения

Объект app.config представляет собой подкласс словаря и поддерживает все стандартные операции.

Встроенные конфигурационные ключи

КлючЗначение по умолчаниюНазначение
DEBUGFalseВключает режим отладки.
TESTINGFalseВключает тестовый режим.
PROPAGATE_EXCEPTIONSNoneПередаёт исключения в тестовом режиме.
PRESERVE_CONTEXT_ON_EXCEPTIONNoneСохраняет контекст запроса при исключении.
TRAP_HTTP_EXCEPTIONSFalseПреобразует HTTP-исключения в обычные.
TRAP_BAD_REQUEST_ERRORSNoneЛовит ошибки типа BadRequest.
SECRET_KEYNoneСекретный ключ для подписи сессий и токенов.
SESSION_COOKIE_NAME'session'Имя cookie для сессии.
SESSION_COOKIE_DOMAINNoneДомен cookie сессии.
SESSION_COOKIE_PATHNoneПуть cookie сессии.
SESSION_COOKIE_HTTPONLYTrueУстанавливает флаг HttpOnly.
SESSION_COOKIE_SECUREFalseТребует HTTPS для отправки cookie.
SESSION_COOKIE_SAMESITE'Lax'Политика SameSite для cookie.
PERMANENT_SESSION_LIFETIMEtimedelta(days=31)Время жизни постоянной сессии.
USE_X_SENDFILEFalseИспользовать X-Sendfile для отдачи файлов.
SERVER_NAMENoneИмя сервера (для генерации абсолютных URL).
APPLICATION_ROOT'/'Корень приложения (для сессий и URL).
PREFERRED_URL_SCHEME'http'Предпочтительная схема URL.
MAX_CONTENT_LENGTHNoneМаксимальный размер тела запроса.
SEND_FILE_MAX_AGE_DEFAULTtimedelta(hours=12)Время кэширования статики.
TEMPLATES_AUTO_RELOADNoneАвтоматическая перезагрузка шаблонов.
EXPLAIN_TEMPLATE_LOADINGFalseВывод информации о загрузке шаблонов.

Методы управления конфигурацией

  • app.config.from_pyfile(filename, silent=False) — загружает конфиг из Python-файла.
  • app.config.from_object(obj) — загружает конфиг из объекта (например, класса).
  • app.config.from_envvar(variable_name, silent=False) — загружает путь к файлу из переменной окружения.
  • app.config.from_file(filename, load_function, silent=False) — загружает конфиг из JSON/YAML через пользовательскую функцию.
  • app.config.from_prefixed_env(prefix='FLASK') — загружает переменные окружения с префиксом (начиная с Flask 2.0).

3. Маршрутизация и представления

Декоратор @app.route

Регистрирует функцию как обработчик запроса по указанному пути.

Параметры:

  • rule — строка маршрута (например, '/user/<username>').
  • endpoint — имя маршрута. По умолчанию — имя функции.
  • methods — список HTTP-методов (например, ['GET', 'POST']).
  • defaults — словарь значений по умолчанию для переменных маршрута.
  • subdomain — поддомен, к которому применяется маршрут.
  • strict_slashes — управляет обработкой завершающего слеша.
  • redirect_to — URL или функция для перенаправления.
  • provide_automatic_options — автоматически обрабатывать OPTIONS-запросы.

Пример:

@app.route('/user/<username>', methods=['GET'], strict_slashes=False)
def profile(username):
return f"Profile of {username}"

Конвертеры переменных в маршрутах

Flask поддерживает следующие встроенные конвертеры:

  • <string:name> — любая строка без слеша (по умолчанию).
  • <int:id> — целое число.
  • <float:value> — число с плавающей точкой.
  • <path:path> — строка, включающая слеши.
  • <uuid:token> — UUID (требует Python 3.7+).

Можно регистрировать собственные конвертеры через app.url_map.converters.


4. Объекты запроса и ответа

request

Глобальный объект, представляющий текущий входящий запрос.

Свойства:

  • method — HTTP-метод (GET, POST и т.д.).
  • url — полный URL запроса.
  • base_url — URL без строки запроса.
  • host — хост запроса.
  • remote_addr — IP-адрес клиента.
  • headers — заголовки запроса (словарь).
  • args — параметры строки запроса (?key=value).
  • form — данные формы (POST).
  • json — тело запроса в формате JSON.
  • files — загруженные файлы.
  • cookies — cookie, отправленные клиентом.
  • is_json — указывает, является ли тело запроса JSON.
  • get_json(force=False, silent=False, cache=True) — безопасное получение JSON.

Response

Объект ответа. Flask автоматически преобразует возвращаемое значение представления в Response.

Явное создание:

from flask import Response
return Response("Hello", status=200, mimetype='text/plain')

Параметры конструктора:

  • response — тело ответа (строка, байты, итератор).
  • status — код состояния HTTP.
  • headers — заголовки ответа.
  • mimetype — MIME-тип (например, 'application/json').
  • content_type — полный Content-Type с кодировкой.

5. Сессии

Flask предоставляет защищённые подписанные cookie-сессии через глобальный объект session.

Использование:

from flask import session

session['user_id'] = 123
user_id = session.get('user_id')
session.pop('user_id', None)

Требования:

  • Обязательно задан SECRET_KEY.
  • Сессия сериализуется в JSON (поддерживаются только простые типы: строки, числа, списки, словари).

Настройки сессии — см. раздел «Конфигурация» выше (SESSION_COOKIE_*).


6. Blueprints

Blueprints — механизм модульной организации приложения. Позволяют группировать маршруты, обработчики ошибок, шаблоны и статические файлы в логически связанные компоненты.

Создание Blueprint

from flask import Blueprint

auth_bp = Blueprint('auth', __name__, url_prefix='/auth')

Параметры конструктора:

  • name — уникальное имя Blueprint’а.
  • import_name — обычно __name__.
  • static_folder, static_url_path, template_folder — аналогичны параметрам Flask.
  • url_prefix — префикс для всех маршрутов внутри Blueprint’а.
  • subdomain — поддомен, к которому применяется Blueprint.
  • url_defaults — значения по умолчанию для переменных URL.

Регистрация Blueprint

app.register_blueprint(auth_bp)

Дополнительные параметры регистрации:

  • url_prefix — может быть переопределён при регистрации.
  • options — словарь дополнительных настроек (например, subdomain).

Blueprints поддерживают собственные before_request, after_request, errorhandler и другие декораторы.


7. Обработка ошибок

Глобальные обработчики ошибок

@app.errorhandler(404)
def not_found(error):
return "Страница не найдена", 404

Поддерживаются как HTTP-коды, так и классы исключений:

from werkzeug.exceptions import BadRequest

@app.errorhandler(BadRequest)
def handle_bad_request(e):
return "Неверный запрос", 400

Возврат JSON при ошибках

В API-приложениях часто требуется возвращать ошибки в формате JSON:

@app.errorhandler(404)
def not_found_json(error):
return jsonify({"error": "Not found"}), 404

Ошибки в Blueprint

Blueprint может иметь собственные обработчики ошибок, которые перекрывают глобальные только для своих маршрутов.


8. Шаблоны и Jinja2

Flask использует шаблонизатор Jinja2 по умолчанию.

Рендеринг шаблона

from flask import render_template

@app.route('/')
def index():
return render_template('index.html', title="Главная")

Настройка Jinja2

Через app.jinja_env можно настраивать:

  • trim_blocks, lstrip_blocks — управление пробелами.
  • autoescape — автоматическое экранирование (включено по умолчанию для .html).
  • filters — регистрация пользовательских фильтров.
  • globals — глобальные переменные в шаблонах.

Пользовательские фильтры

@app.template_filter('reverse')
def reverse_filter(s):
return s[::-1]

Использование в шаблоне: {{ name|reverse }}.

Макросы и наследование

Jinja2 поддерживает макросы ({% macro %}) и наследование шаблонов ({% extends %}, {% block %}).


9. Сигналы (Signals)

Flask использует систему сигналов через библиотеку blinker. Сигналы позволяют подписываться на события без прямого вызова функций.

Основные сигналы

  • request_started — начало обработки запроса.
  • request_finished — завершение запроса.
  • got_request_exception — возникновение исключения.
  • template_rendered — рендеринг шаблона.
  • signals_available — проверка доступности сигналов.

Пример подписки

from flask import got_request_exception

def log_exception(sender, exception, **extra):
print(f"Exception: {exception}")

got_request_exception.connect(log_exception, app)

Сигналы полезны для логирования, аудита, интеграции с внешними системами.


10. Командная строка (CLI)

Flask предоставляет встроенную поддержку CLI через Click.

Регистрация команды

@app.cli.command()
def init_db():
"""Инициализация базы данных."""
print("Database initialized")

Запуск: flask init_db.

Команды с параметрами

import click

@app.cli.command()
@click.option('--count', default=1, help='Number of greetings.')
def greet(count):
for _ in range(count):
print("Hello!")

Автоматическое обнаружение

Если переменная окружения FLASK_APP указывает на модуль, Flask автоматически загружает все зарегистрированные команды.


11. Тестирование

Flask предоставляет инструменты для интеграционного тестирования.

Клиент для тестов

with app.test_client() as client:
response = client.get('/')
assert response.status_code == 200

Контекст приложения в тестах

with app.app_context():
# Выполнение кода в контексте приложения
pass

Фикстуры и временные данные

Рекомендуется использовать pytest или unittest в сочетании с test_client() и app_context().


12. Работа с файлами и медиа

Отправка файлов

from flask import send_file

@app.route('/download')
def download():
return send_file('path/to/file.pdf', as_attachment=True)

Загрузка файлов

@app.route('/upload', methods=['POST'])
def upload():
file = request.files['file']
file.save('/uploads/' + file.filename)
return "Файл сохранён"

Ограничения:

  • Установите MAX_CONTENT_LENGTH в конфигурации.
  • Проверяйте расширения и MIME-типы вручную — Flask не делает этого автоматически.

13. Расширения

Flask имеет богатую экосистему расширений. Расширения обычно инициализируются так:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()
db.init_app(app)

Популярные расширения

  • Flask-SQLAlchemy — ORM поверх SQLAlchemy.
  • Flask-WTF — работа с формами и CSRF-защитой.
  • Flask-Login — управление сессиями пользователей.
  • Flask-Mail — отправка email.
  • Flask-CORS — поддержка CORS.
  • Flask-Migrate — миграции базы данных через Alembic.
  • Flask-RESTful — создание REST API.
  • Flask-JWT-Extended — аутентификация через JWT.

Расширения следуют соглашению: init_app(app) для отложенной инициализации.


14. Производительность и масштабируемость

Режим разработки vs продакшен

  • В режиме DEBUG=True включены перезагрузка кода и отладчик.
  • Для продакшена используйте WSGI-сервер (Gunicorn, uWSGI) за обратным прокси (Nginx).

Асинхронность

Начиная с Flask 2.0, поддерживаются асинхронные представления:

@app.route('/async')
async def async_view():
await some_async_operation()
return "Done"

Требуется ASGI-сервер (например, Hypercorn или Daphne).

Кэширование

Flask не включает кэширование по умолчанию. Используйте Flask-Caching с бэкендами: Redis, Memcached, простой словарь.


15. Безопасность

Защита от основных угроз

  • CSRF: используйте Flask-WTF или Flask-SeaSurf.
  • XSS: Jinja2 автоматически экранирует переменные в шаблонах.
  • SQL-инъекции: используйте ORM или параметризованные запросы.
  • Clickjacking: добавьте заголовок X-Frame-Options: DENY.
  • Session fixation: регенерируйте сессию после входа.

Заголовки безопасности

Рекомендуется использовать Flask-Talisman для автоматической настройки безопасных заголовков (HSTS, CSP, XSS-Protection и др.).


16. Middleware и WSGI-уровень

Flask основан на спецификации WSGI (Web Server Gateway Interface). Приложение Flask само является WSGI-приложением и может быть обёрнуто в middleware.

Пример простого middleware

class PrefixMiddleware:
def __init__(self, app, prefix):
self.app = app
self.prefix = prefix

def __call__(self, environ, start_response):
if environ['PATH_INFO'].startswith(self.prefix):
environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]
environ['SCRIPT_NAME'] = self.prefix
return self.app(environ, start_response)
else:
start_response('404 Not Found', [('Content-Type', 'text/plain')])
return [b'Not Found']

Подключение:

app.wsgi_app = PrefixMiddleware(app.wsgi_app, '/api')

Распространённые WSGI-мидлвары

  • ProxyFix (из Werkzeug) — корректирует заголовки при работе за обратным прокси.
  • DispatcherMiddleware — объединяет несколько приложений под разными путями.
  • SharedDataMiddleware — отдаёт статику (полезно в разработке без Nginx).

17. Контексты приложения и запроса

Flask использует два типа контекстов:

  • Контекст приложения (app_context) — содержит данные, общие для всего приложения (например, подключение к БД).
  • Контекст запроса (request_context) — содержит данные, относящиеся к текущему HTTP-запросу.

Когда нужны контексты?

  • В фоновых задачах (Celery, потоки).
  • При запуске кода вне обработчика запроса (например, в CLI или тестах).

Пример использования

with app.app_context():
# Доступ к current_app, g, db и другим глобальным объектам
user = User.query.get(1)

Глобальные объекты

  • current_app — текущее приложение.
  • g — временный объект для хранения данных в течение одного запроса.
  • request, session, url_for — работают только внутри контекста запроса.

18. Логирование

Flask использует стандартный модуль logging Python.

Настройка логгера

import logging

app.logger.setLevel(logging.INFO)
handler = logging.FileHandler('app.log')
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
app.logger.addHandler(handler)

Использование

@app.route('/')
def index():
app.logger.info("Главная страница загружена")
return "OK"

В режиме DEBUG=True логи автоматически выводятся в консоль.


19. Интернационализация (i18n)

Flask не включает i18n по умолчанию, но легко интегрируется с Babel.

Установка и настройка

pip install Flask-Babel
from flask_babel import Babel, gettext

babel = Babel(app)

@babel.localeselector
def get_locale():
return request.accept_languages.best_match(['en', 'ru'])

Использование в шаблонах:

{{ _('Hello') }}

Компиляция переводов осуществляется через команды pybabel.


20. Работа с WebSocket и реального времени

Flask сам по себе не поддерживает WebSocket. Для этого используются расширения:

  • Flask-SocketIO — реализует протокол Socket.IO поверх WebSocket и long polling.
  • Quart — асинхронный клон Flask с нативной поддержкой WebSocket (альтернатива, а не расширение).

Пример с Flask-SocketIO

from flask_socketio import SocketIO, emit

socketio = SocketIO(app)

@socketio.on('connect')
def handle_connect():
emit('response', {'data': 'Connected'})

if __name__ == '__main__':
socketio.run(app)

21. Деплой и производственная эксплуатация

Требования к продакшену

  • Отключите DEBUG.
  • Установите надёжный SECRET_KEY.
  • Используйте WSGI-сервер (Gunicorn, uWSGI).
  • Разместите приложение за обратным прокси (Nginx, Apache).
  • Настройте HTTPS.

Пример запуска через Gunicorn

gunicorn -w 4 -b 0.0.0.0:8000 myapp:app

Docker-образ

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "myapp:app"]

22. Мониторинг и метрики

  • Логирование ошибок: Sentry, Loggly, ELK.
  • Метрики: Prometheus + Flask-Exporter.
  • Профилирование: flask-profiler, py-spy.

Пример подключения Prometheus:

from prometheus_flask_exporter import PrometheusMetrics

metrics = PrometheusMetrics(app)

Автоматически экспортирует метрики по /metrics.


23. Типовая структура проекта

Хотя Flask не навязывает структуру, рекомендуется следующая организация:

myproject/
├── app/
│ ├── __init__.py # Создание экземпляра Flask
│ ├── models.py # Модели данных (если нет ORM-слоя)
│ ├── routes/
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── auth.py
│ ├── templates/
│ ├── static/
│ └── utils.py
├── migrations/ # Alembic миграции
├── tests/
├── config.py # Конфигурационные классы
├── requirements.txt
├── run.py # Точка входа
└── instance/ # Файлы экземпляра (если используется)

Для крупных проектов — переход на архитектуру по Blueprint’ам или даже на пакетную структуру с app/main/, app/auth/ и т.д.


24. Полезные функции и утилиты из flask и werkzeug

ФункцияНазначение
url_for(endpoint, **values)Генерация URL по имени маршрута.
redirect(location, code=302)Перенаправление клиента.
abort(code)Выбрасывает HTTP-исключение (например, abort(404)).
make_response(rv)Преобразует возвращаемое значение в объект Response.
safe_join(directory, *pathnames)Безопасное объединение путей (защита от directory traversal).
secure_filename(filename)Очистка имени файла от опасных символов.
escape(s)Экранирование HTML (устаревшее, лучше использовать Jinja2).

25. Совместимость и версионность

  • Flask 2.0+ требует Python 3.7+.
  • Flask 3.0 (ожидается) будет требовать Python 3.9+.
  • Werkzeug и Jinja2 обновляются вместе с Flask.
  • Расширения могут отставать — проверяйте совместимость в requirements.txt.